# -*- coding: utf-8 -*-

import json
import logging
from datetime import datetime, timedelta

from django.views.generic import TemplateView
from django.utils.encoding import smart_unicode
from django.utils.decorators import method_decorator
from django.views.decorators.http import require_POST, require_GET
from common.cache import redis_cache
from common.account.db import account as account_db
from common.cache.redis_cache import set_available_withdraw_channels, get_available_withdraw_channels
from common.transaction import calc_withdraw_amount
from common.transaction.model import CHECK_STATUS
from common.transaction import db as transaction_db
from common.stats.withdraw import query_same_withdraw_user, list_withdraw_account
from common.utils import exceptions as err
from common.utils.decorator import response_wrapper
from common.utils.tz import utc_to_local_str, get_utc_date
from common.utils.api import token_required, check_params, mask_string
from common.utils.export import redirect_to_file, gen_filename
from async import async_job
from common.transaction.model import WITHDRAW_STATUS
from common.black_account.db import (list_withdraw_black, update_withdraw_black, get_withdraw_black_modification_list,
                                     get_user_black_modification_dict, get_black_info_list)
from common.black_account.model import (WITHDRAW_BLACK_STATUS, WITHDRAW_BLACK_TYPE)


_LOGGER = logging.getLogger(__name__)


class WithdrawView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        export = query_dct.pop('$export', None)
        user_id = query_dct.get('user_id', None)
        is_extend = query_dct.get('is_extend', False)
        is_fresh = query_dct.get('is_fresh', False)
        if is_fresh and int(is_fresh) and 'created_at' not in query_dct and 'updated_at' not in query_dct:
            today = get_utc_date() + timedelta(hours=8)
            query_dct['created_at'] = json.dumps({"$gte": str(today)})
        if not user_id and not is_extend:
            return {}
        if export:
            # TODO: 导出提现记录信息
            filename = gen_filename('withdraw_records')
            cn_header = [
                u'提现单号', u'用户ID', u'提现金额', u'实际金额', u'提现方式',
                u'提现通道', u'提现时间', u'提现状态', u'更新时间', u'姓名',
                u'联系方式', u'账户信息1', u'账户信息2', u'第三方流水号', u'交易时间']
            data = transaction_db.export_withdraw_records(query_dct)
            return redirect_to_file(data, cn_header, filename)

        items, total_count = transaction_db.list_withdraw_records(query_dct)

        resp_items = []
        for item in items:
            data = item.as_dict()
            data['id'] = str(data['id'])
            data['real_cash_price'] = calc_withdraw_amount(data['user_id'], data['price'])
            data['created_at'] = utc_to_local_str(data['created_at'])
            data['updated_at'] = utc_to_local_str(data['updated_at'])
            data['withdraw_info'] = json.loads(data['extend'] or '{}')
            resp_items.append(data)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    def post(self, req):
        parmas_dct = json.loads(req.body)
        check_params(parmas_dct, ('ids', 'status'))
        transaction_db.batch_update_withdraws(req.user_id, parmas_dct['ids'], int(parmas_dct['status']))
        if parmas_dct['status'] == WITHDRAW_STATUS.DONE:
            async_job.stats_withdraw.delay(parmas_dct['ids'])
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(WithdrawView, self).dispatch(*args, **kwargs)


class SingleWithdrawView(TemplateView):
    def get(self, req, withdraw_id):
        item = transaction_db.get_withdraw(int(withdraw_id))
        data = item.as_dict()
        data['real_cash_price'] = calc_withdraw_amount(data['user_id'], data['cash_price'])
        data['created_at'] = utc_to_local_str(data['created_at'])
        data['updated_at'] = utc_to_local_str(data['updated_at'])
        data['content'] = json.loads(item.extend or '{}')
        return data

    def post(self, req, withdraw_id):
        data = json.loads(req.body)
        transaction_db.update_withdraw_status(req.user_id, withdraw_id, data)
        return {}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(SingleWithdrawView, self).dispatch(*args, **kwargs)


@require_POST
@response_wrapper
@token_required
def check_withdraw(req, withdraw_id, check_status):
    withdraw_id = int(withdraw_id)
    check_status = int(check_status)
    if check_status not in (CHECK_STATUS.SUCC, CHECK_STATUS.FAIL):
        raise err.ParamError('invalid check_status')
    data = json.loads(req.body)
    transaction_db.check_withdraw(req.user_id, withdraw_id, check_status,
        reason=data.get('reason'))
    _LOGGER.info('check_withdraw succ, %s-%s-%s', req.user_id, withdraw_id, check_status)
    return {}


@require_POST
@response_wrapper
@token_required
def batch_check_withdraw(req):
    parmas_dct = json.loads(req.body)
    check_params(parmas_dct, ('ids', 'check_status'))
    transaction_db.batch_check_withdraws(req.user_id, parmas_dct['ids'], int(parmas_dct['check_status']))
    return {}


@require_POST
@response_wrapper
@token_required
def set_black_uids(req):
    admin_id = req.user_id
    query_dct = json.loads(req.body)
    status = query_dct.get("status", WITHDRAW_BLACK_STATUS.ENABLE)
    type = unicode(query_dct.get("type"))
    type_account = unicode(query_dct.get("type_account"))
    if type in [WITHDRAW_BLACK_TYPE.TEST_UID, WITHDRAW_BLACK_TYPE.BLACK_UID,
                WITHDRAW_BLACK_TYPE.BLACK_BANK, WITHDRAW_BLACK_TYPE.BLACK_PHONE]\
            and not str(type_account).isdigit():
        raise err.ParamError('type_account must only number')
    info = {'type_account': type_account, 'type': type, 'money': query_dct.get("money"),
            'note': query_dct.get("note"), 'reason': query_dct.get('reason')}
    update_withdraw_black(info, admin_id, status)
    return {}


@require_GET
@response_wrapper
@token_required
def get_black_uids(req):
    query_dct = req.GET.dict()
    export = query_dct.pop('$export', None)
    if export:
        filename = gen_filename('black')
        cn_header = [u'用户ID', u'手机号', u'注册时间']

    items, total = list_withdraw_black(query_dct)
    resp_items = []
    for item in items:
        data = item.as_dict()
        data['created_at'] = utc_to_local_str(data['created_at'])
        data['updated_at'] = utc_to_local_str(data['updated_at'])
        resp_items.append(data)

    if export:
        resp = []
        for i in resp_items:
            uid = int(i['type_account'])
            account = account_db.get_account(uid)
            resp.append([uid, account.phone, utc_to_local_str(account.created_at)])
        return redirect_to_file(resp, cn_header, filename)
    return {'list': resp_items, 'page': 1, 'size': len(resp_items),
            'stock': [], 'total_count': total}


@require_GET
@response_wrapper
@token_required
def get_limit(req):
    """
    获取限制金额
    """
    amount = redis_cache.get_limit_amount()
    return {'amount': amount}


@require_POST
@response_wrapper
@token_required
def set_limit(req):
    """
    设定限制金额
    """
    data = json.loads(req.body)
    amount = data.get('amount')
    redis_cache.set_limit_amount(int(amount))
    return {}


@require_GET
@response_wrapper
@token_required
def query_withdraw_duplicate(req, withdraw_type, withdraw_no):
    user_number = query_same_withdraw_user(withdraw_type, withdraw_no)
    return {
        'count': user_number
    }


class WithdrawAccountView(TemplateView):
    def get(self, req):
        query_dct = req.GET.dict()
        export = query_dct.pop('$export', None)
        if export:
            # 导出记录信息
            filename = gen_filename('withdraw_account')
            cn_header = [
                u'用户ID', u'提现方式', u'提现帐号', u'提现姓名', u'累计金额', u'累计次数'
            ]
        items, total_count = list_withdraw_account(query_dct)

        resp_items = []
        for item in items:
            item['id'] = str(item['_id'])
            item['no'] = mask_string(item['no'])
            item['created_at'] = utc_to_local_str(item['created_at'])
            item['updated_at'] = utc_to_local_str(item['last_ts'])
            if export:
                if item['type'] == 0:
                    withdraw_type = u'银行卡'
                else:
                    withdraw_type = u'支付宝'
                export_item = (item['user_id'], withdraw_type, item['no'],
                               item['name'], item['amount'], item['count'])
                resp_items.append(export_item)
            else:
                resp_items.append(item)

        if export:
            return redirect_to_file(resp_items, cn_header, filename)

        return {'list': resp_items, 'page': query_dct.get('$page', 1),
                'size': len(resp_items), 'total_count': total_count}

    @method_decorator(response_wrapper)
    @method_decorator(token_required)
    def dispatch(self, *args, **kwargs):
        return super(WithdrawAccountView, self).dispatch(*args, **kwargs)


@require_GET
@response_wrapper
@token_required
def get_withdraw_channels(req):
    return {'channels': list(get_available_withdraw_channels())}


@require_POST
@response_wrapper
@token_required
def set_withdraw_channels(req):
    data = json.loads(req.body)
    channels = data.get('channels')
    set_available_withdraw_channels(*channels)
    return {}


@require_GET
@response_wrapper
@token_required
def get_black_modification(req):
    query_dct = req.GET.dict()
    disable_paginate = query_dct.get('disable_paginate', False)
    params, total_count = get_withdraw_black_modification_list(query_dct, disable_paginate)
    resp_items = []
    for param in params:
        data = param.as_dict()
        data['created_at'] = utc_to_local_str(data['created_at'])
        resp_items.append(data)
    return {'list': resp_items, 'total_count': total_count}


@require_GET
@response_wrapper
@token_required
def get_user_black_modification(req):
    query_dct = req.GET.dict()
    user_id = query_dct.get('user_id')
    if user_id:
        return get_user_black_modification_dict(user_id)
    return {}


@require_GET
@response_wrapper
@token_required
def get_black_info(req):
    query_dct = req.GET.dict()
    total_count, datas = get_black_info_list(query_dct)
    return {'data': datas, 'total_count': total_count}
